﻿using Core.Info;
using Core.Utility.Helper;
using Newtonsoft.Json;
using NPOI.POIFS.Crypt.Dsig;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.Utility
{
    /// <summary>
    /// 返回结果信息，通常用于方法返回bool型结果后，仍需要额外返回信息
    /// </summary>
    public class ReturnResultInfo: ReturnResultInfo<object>, IReturnResultInfo
    {
        /// <summary>
        /// 默认构造
        /// </summary>
        public ReturnResultInfo(bool successed = false, string? message = "操作失败",string? topic = "", string? info = "操作失败") :base(successed, message,topic, info)
        {

        }

        /// <summary>
        /// 类型转换，将除Data属性以外的属性原样赋值转换
        /// </summary>
        /// <typeparam name="TSourceData"></typeparam>
        /// <param name="resultData"></param>
        /// <param name="resultInfo"></param>
        /// <returns></returns>
        public static ReturnResultInfo Convert<TSourceData>(ReturnResultInfo<TSourceData> resultInfo, object? resultData = default)
        {
            ReturnResultInfo returnResultInfo = new ReturnResultInfo();
            returnResultInfo.Topic = resultInfo.Topic;
            returnResultInfo.Successed = resultInfo.Successed;
            returnResultInfo.Message = resultInfo.Message;
            returnResultInfo.Info = resultInfo.Info;
            returnResultInfo.Data = resultData;
            return returnResultInfo;
        }
    }

    /// <summary>
    /// 返回结果信息，通常用于方法返回bool型结果后，仍需要额外返回信息
    /// </summary>
    public class ReturnResultInfo<TData>:IReturnResultInfo<TData>
    {

        /// <summary>
        /// 默认构造
        /// </summary>
        public ReturnResultInfo(bool successed = false, string? message = "操作失败",string? topic = "", string? info = "操作失败")
        {
            this.Successed = successed;
            this.Topic = topic;
            this.Message = message;
            this.Info = info;
            if (string.IsNullOrEmpty(info))
            {
                this.Info = message;
            }
        }

        /// <summary>
        /// 执行成功标志
        /// </summary>
        [JsonProperty("successed", Order = 0)]
        public virtual bool Successed { get; set; } = false;

        /// <summary>
        /// 主题
        /// </summary>
        [JsonProperty("topic", Order = 0)]
        public virtual string? Topic { get; set; } = "";

        /// <summary>
        /// 友好提示信息，通常用于直接呈现给用户的提示信息，在调试模式下， 将输出详细信息
        /// </summary>    
        /// <example>接口调用成功</example>
        [JsonProperty("message", Order = 1)]
        public virtual string? Message { get; set; } = "操作失败";


        /// <summary>
        /// 友好提示信息(包含Topic)，通常用于直接呈现给用户的提示信息，在调试模式下， 将输出详细信息
        /// </summary>
        public virtual string? TopicMessage
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                if (!string.IsNullOrEmpty(Topic))
                {
                    sb.AppendLine(Topic);
                }
                sb.AppendLine(Message ?? "");
                return sb.ToString();
            }
        }

        private string? info;
        /// <summary>
        /// 执行返回的信息，非友好提示，将异常信息等处理至此；若未指定 <see cref="Info"/> 的值，将返回 <see cref="Message"/> 的值
        /// </summary>
        /// <example>操作成功</example>
        [JsonProperty("info", Order = 2)]
        public virtual string? Info
        {
            get
            {
                if(string.IsNullOrEmpty(info))
                {
                    return Message;
                }
                else
                {
                    return info;
                }
            }
            set => info = value;
        }

        /// <summary>
        /// 执行返回的信息（包含Topic），非友好提示，将异常信息等处理至此；若未指定 <see cref="Info"/> 的值，将返回 <see cref="Message"/> 的值
        /// </summary>
        public virtual string? TopicInfo
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                if (!string.IsNullOrEmpty(Topic))
                {
                    sb.AppendLine(Topic);
                }
                sb.AppendLine(Info ?? "");
                return sb.ToString();
            }
        }

        /// <summary>
        /// 执行返回的信息（包含Topic），根据 <see cref="RunTimeInfo.IsDebug"/> 
        /// 与 <see cref="RunTimeInfo.IsDevelopment"/> 决定输出友好信息(TopicMessage)还是详细信息(TopicInfo)
        /// </summary>
        public virtual string? TopicOutput
        {
            get
            {
                if (RunTimeInfo.IsDebug || RunTimeInfo.IsDevelopment)
                {
                    return TopicInfo;
                }
                else
                {
                    return TopicMessage;
                }
            }
        }

        /// <summary>
        /// 执行返回的信息（包含Topic），
        /// 根据 <see cref="RunTimeInfo.IsDebug"/> 
        /// 与 <see cref="RunTimeInfo.IsDevelopment"/> 决定输出友好信息(Message)还是详细信息(Info)
        /// </summary>
        public virtual string? Output
        {
            get
            {
                if (RunTimeInfo.IsDebug || RunTimeInfo.IsDevelopment)
                {
                    return Info;
                }
                else
                {
                    return Message;
                }
            }
        }

        /// <summary>
        /// 用于请求成功后携带的数据
        /// </summary>
        [JsonProperty("data", Order = 3)]
        public virtual TData? Data { get; set; }

        /// <summary>
        /// 设置为成功 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="topic">主题</param>
        /// <param name="data"></param>
        /// <param name="info"></param>
        public void SetSuccess(TData? data = default(TData),string message = "操作成功",string? topic = "",string info = "")
        {
            this.Successed = true;
            if (!string.IsNullOrEmpty(topic))
            {
                this.Topic = topic;
            }
            this.Message = message;
            this.Data = data;
            if(string.IsNullOrWhiteSpace(info))
            {
                info = message;
            }
            this.Info = info;
        }

        /// <summary>
        /// 设置为失败
        /// </summary>
        /// <param name="message">友好提示信息</param>
        /// <param name="topic"></param>
        /// <param name="info">非友好提示信息</param>
        /// <param name="data">失败时携带的参数</param>
        public void SetFailure(string? message = "操作失败",string? topic = "", string? info = "",TData? data = default(TData))
        {
            this.Successed = false; 
            if (!string.IsNullOrEmpty(topic))
            {
                this.Topic = topic;
            }
            this.Message = message;
            this.Data = data;
            if (string.IsNullOrWhiteSpace(info))
            {
                info = message;
            }
            this.Info = info;
        }

        /// <summary>
        /// 设置为异常信息
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="ex"></param>
        public void SetException(string? topic,Exception ex)
        {
            this.Successed = false;
            if (!string.IsNullOrEmpty(topic))
            {
                this.Topic = topic;
            }
            this.Message = ExceptionMessageHelper.OutputMessage(ex, this.Topic);
            this.Info = ExceptionMessageHelper.OutputInfo(ex,topic: this.Topic);
        }
        
        /// <summary>
        /// 设置为异常信息
        /// </summary>
        /// <param name="ex"></param>
        public void SetException(Exception ex)
        {
            this.Successed = false;
            this.Message = ExceptionMessageHelper.OutputMessage(ex, this.Topic);
            this.Info = ExceptionMessageHelper.OutputInfo(ex, topic: this.Topic);
        }
        /// <summary>
        /// 类型转换，将除Data属性以外的属性原样赋值转换
        /// </summary>
        /// <typeparam name="TResultData"></typeparam>
        /// <typeparam name="TSourceData"></typeparam>
        /// <param name="resultInfo"></param>
        /// <param name="resultData"></param>
        /// <returns></returns>
        public static ReturnResultInfo<TResultData> Convert<TResultData, TSourceData>(ReturnResultInfo<TSourceData> resultInfo, TResultData? resultData = default(TResultData))
        {
            ReturnResultInfo<TResultData> returnResultInfo = new ReturnResultInfo<TResultData>();
            returnResultInfo.Topic = resultInfo.Topic;
            returnResultInfo.Successed = resultInfo.Successed;
            returnResultInfo.Message = resultInfo.Message;
            returnResultInfo.Info = resultInfo.Info;
            returnResultInfo.Data = resultData;
            return returnResultInfo;
        }


        /// <summary>
        /// 类型转换，将除Data属性以外的属性原样赋值转换
        /// </summary>
        /// <typeparam name="TResultData"></typeparam>
        /// <param name="resultInfo"></param>
        /// <param name="resultData"></param>
        /// <returns></returns>
        public static ReturnResultInfo<TResultData> Convert<TResultData>(ReturnResultInfo resultInfo, TResultData? resultData = default(TResultData))
        {
            ReturnResultInfo<TResultData> returnResultInfo = new ReturnResultInfo<TResultData>();
            returnResultInfo.Topic = resultInfo.Topic;
            returnResultInfo.Successed = resultInfo.Successed;
            returnResultInfo.Message = resultInfo.Message;
            returnResultInfo.Info = resultInfo.Info;
            returnResultInfo.Data = resultData;            
            return returnResultInfo;
        }
    }

    /// <summary>
    /// 返回结果信息，通常用于方法返回bool型结果后，仍需要额外返回信息
    /// </summary>
    public interface IReturnResultInfo:IReturnResultInfo<object>
    {

    }

    /// <summary>
    /// 返回结果信息，通常用于方法返回bool型结果后，仍需要额外返回信息
    /// </summary>
    /// <typeparam name="TData"></typeparam>
    public interface IReturnResultInfo<TData>
    {
        /// <summary>
        /// 用于请求成功后携带的数据
        /// </summary>
        [JsonProperty("successed", Order = 1)]
        public bool Successed { get; set; }

        /// <summary>
        /// 用于请求成功后携带的数据
        /// </summary>
        [JsonProperty("topic", Order = 2)]
        public string? Topic { get; set; }

        /// <summary>
        /// 友好提示信息，通常用于直接呈现给用户的提示信息
        /// </summary>    
        /// <example>接口调用成功</example>
        [JsonProperty("message", Order = 3)]
        public string? Message { get; set; }

        /// <summary>
        /// 友好提示信息(包含Topic)，通常用于直接呈现给用户的提示信息
        /// </summary>
        [JsonIgnore]
        public string? TopicMessage { get; }

        /// <summary>
        /// 执行返回的信息，非友好提示，将异常信息等处理至此；若未指定 <see cref="Info"/> 的值，将返回 <see cref="Message"/> 的值
        /// </summary>
        /// <example>操作成功</example>
        [JsonProperty("info", Order = 4)]
        public string? Info { get; set; }

        /// <summary>
        /// 执行返回的信息,包含Topic，非友好提示，将异常信息等处理至此；若未指定 <see cref="Info"/> 的值，将返回 <see cref="Message"/> 的值
        /// </summary>
        /// <example>操作成功</example>
        [JsonIgnore]
        public string? TopicInfo { get; }

        /// <summary>
        /// 根据 <see cref="RunTimeInfo.IsDebug"/> 与 <see cref="RunTimeInfo.IsDevelopment"/> 决定输出友好信息(TopicMessage)还是详细信息(TopicInfo)
        /// </summary>
        /// <example>操作成功</example>
        [JsonIgnore]
        public string? TopicOutput { get; }

        /// <summary>
        /// 根据 <see cref="RunTimeInfo.IsDebug"/> 与 <see cref="RunTimeInfo.IsDevelopment"/> 决定输出友好信息(Message)还是详细信息(Info)
        /// </summary>
        /// <example>操作成功</example>
        [JsonIgnore]
        public string? Output { get; }

        /// <summary>
        /// 用于请求成功后携带的数据
        /// </summary>
        [JsonProperty("data", Order = 5)]
        public TData? Data { get; set; }

        /// <summary>
        /// 设置为操作成功的快捷方法
        /// </summary>
        /// <param name="message"></param>
        /// <param name="data"></param>
        /// <param name="topic">主题</param>
        public void Success(string? message = "操作成功", TData? data = default(TData), string? topic = "")
        {
            Successed = true;
            Topic = topic;
            Message = message;
            Data = data;
        }

        /// <summary>
        /// 设置为操作失败的快捷方法
        /// </summary>
        /// <param name="message"></param>
        /// <param name="data"></param>
        /// <param name="topic">主题</param>
        public void Fail(string message = "操作失败",TData? data = default(TData), string? topic = "")
        {
            Successed = false;
            Message = message;
            Data = data;
        }
    }
}
